<template>
    <div class="left-tree-container">
        <j-input
            v-model:value="searchValue"
            @change="search"
            placeholder="请输入组织名称"
            class="search-input"
            allowClear
        >
            <template #suffix>
                <AIcon type="SearchOutlined" />
            </template>
        </j-input>
        <div class="add-btn">
            <PermissionButton
                type="primary"
                :hasPermission="`${permission}:add`"
                @click="openDialog()"
            >
                新增
            </PermissionButton>
        </div>

        <div class="tree">
            <j-spin :spinning="loading">
                <jTree
                    v-if="treeData.length > 0"
                    :tree-data="treeData"
                    v-model:selected-keys="selectedKeys"
                    v-model:expandedKeys="expandedKeys"
                    :fieldNames="{ key: 'id' }"
                    :showLine="{ showLeafIcon: false }"
                    :show-icon="true"
                >
                    <template #title="{ name, data }">
                        <div class="department-tree-item-content">
                            <span class="title">
                                <j-ellipsis>
                                    {{ name }}
                                </j-ellipsis>
                            </span>
                            <span
                                class="func-btns"
                                @click="(e) => e.stopPropagation()"
                            >
                                <PermissionButton
                                    :hasPermission="`${permission}:update`"
                                    type="link"
                                    :tooltip="{
                                        title: '编辑',
                                    }"
                                    @click="openDialog(data)"
                                >
                                    <AIcon type="EditOutlined" />
                                </PermissionButton>
                                <PermissionButton
                                    :hasPermission="`${permission}:add`"
                                    type="link"
                                    :tooltip="{
                                        title: '新增子组织',
                                    }"
                                    @click="
                                        openDialog({
                                            ...data,
                                            id: '',
                                            parentId: data.id,
                                        })
                                    "
                                >
                                    <AIcon type="PlusCircleOutlined" />
                                </PermissionButton>
                                <PermissionButton
                                    type="link"
                                    :hasPermission="`${permission}:delete`"
                                    :tooltip="{ title: '删除' }"
                                    :popConfirm="{
                                        title: `确认删除？`,
                                        onConfirm: () => delDepartment(data.id),
                                    }"
                                >
                                    <AIcon type="DeleteOutlined" />
                                </PermissionButton>
                            </span>
                        </div>
                    </template>
                </jTree>
                <j-empty v-else description="暂无数据" />
            </j-spin>
        </div>
        <!-- 编辑弹窗 -->
        <EditDepartmentDialog
            v-if="dialog.visible"
            v-model:visible="dialog.visible"
            :tree-data="sourceTree"
            :data="dialog.selectItem"
            @refresh="refresh"
        />
    </div>
</template>

<script setup lang="ts">
import PermissionButton from '@/components/PermissionButton/index.vue';
import { getTreeData_api, delDepartment_api } from '@/api/system/department';
import { debounce, cloneDeep, omit } from 'lodash-es';
import { ArrayToTree } from '@/utils/utils';
import EditDepartmentDialog from './EditDepartmentDialog.vue';
import { onlyMessage } from '@/utils/comm';
const route = useRoute();
const permission = 'system/Department';

const save = useRoute().query.save;
const emits = defineEmits(['change']);
const searchValue = ref(''); // 搜索内容
const loading = ref<boolean>(false); // 数据加载状态
const sourceTree = ref<any[]>([]); // 源数据
const treeMap = new Map(); // 数据的map版本
const treeData = ref<any[]>([]); // 展示的数据
const selectedKeys = ref<string[]>([]); // 当前选中的项
const expandedKeys = ref<string[] | number[]>([]);
function findParents(tree:any, targetId:any) {
    let parents:any = [];
    function findAndCollectParents(node:any) {
        if (node.id === targetId) {
            return true;
        }
        // Recursively check children
        if (node.children) {
            for (let child of node.children) {
                if (findAndCollectParents(child)) {
                    // If child node found the target, add current node to parents list
                    parents.push(node.id);
                    return true;
                }
            }
        }

        return false;
    }
    // Traverse the tree and find the target node
    for (let node of tree) {
        if (findAndCollectParents(node)) {
            break; // Stop once we found the target node and collected all parents
        }
    }
    // Reverse the array to have parents from root to immediate parent
    parents.reverse();

    return parents;
}

function getTree(cb?: Function) {
    loading.value = true;
    const params = {
        paging: false,
        sorts: [{ name: 'sortIndex', order: 'asc' }],
    } as any;
    if (searchValue.value) {
        params.terms = [
            { column: 'name$LIKE', value: `%${searchValue.value}%` },
        ];
    }
    treeMap.clear();
    getTreeData_api(params)
        .then((resp: any) => {
            sourceTree.value = resp.result.sort((a: any, b: any) =>
                a.sortIndex === b.sortIndex
                    ? b.createTime - a.createTime
                    : a.sortIndex - b.sortIndex,
            ); // 报存源数据
            if (route.query?.id) {
                expandedKeys.value = findParents(sourceTree.value, route.query.id);
                selectedKeys.value = [route.query.id];
            } else {
                selectedKeys.value = [resp.result[0]?.id];
            }
            handleTreeMap(resp.result); // 将树形结构转换为map结构
            treeData.value = resp.result; // 第一次不用进行过滤
            cb && cb();
        })
        .finally(() => {
            loading.value = false;
        });
}
const search = debounce(() => {
    const key = searchValue.value;
    const treeArray = new Map();
    if (key) {
        const searchTree: string[] = [];
        treeMap.forEach((item) => {
            if (item.name.includes(key)) {
                searchTree.push(item.parentId);
                treeArray.set(item.id, item);
            }
        });
        expandedKeys.value = [];
        dig(searchTree);
        treeData.value = ArrayToTree(cloneDeep([...treeArray.values()]));
    } else {
        getTree()
        treeData.value = ArrayToTree(cloneDeep([...treeMap.values()]));
        expandedKeys.value = [];
    }

    function dig(_data: any[]): any {
        const pIds: string[] = [];
        if (!_data.length) return;
        _data.forEach((item) => {
            if (treeMap.has(item)) {
                const _item = treeMap.get(item);
                pIds.push(_item.parentId);
                treeArray.set(item, _item);
                expandedKeys.value.push(_item.id);
                if (pIds.length > 0) {
                    dig(pIds);
                }
            }
        });
    }
}, 500);
// 将树形数组转化为map形式，以便筛选时操作
function handleTreeMap(_data: any[]) {
    if (_data) {
        _data.map((item) => {
            treeMap.set(item.id, omit(cloneDeep(item), ['children']));
            if (item.children) {
                handleTreeMap(item.children);
            }
        });
    }
}
// 删除部门
function delDepartment(id: string) {
    const response = delDepartment_api(id);
    response.then(() => {
        onlyMessage('操作成功');
        getTree();
    });
    return response;
}
function refresh(id: string) {
    // @ts-ignore
    if (window?.onTabSaveSuccess) {
        window.onTabSaveSuccess(id);
        setTimeout(() => window.close(), 300);
    }
    getTree();
}

// 弹窗
const dialog = reactive({
    visible: false,
    selectItem: {},
});
const openDialog = (row: any = {}) => {
    // 计算默认排序值，为子列表中最大的排序值+1
    let sortIndex = row.sortIndex || 1;
    if (!row.id) {
        let children = [] as any[];
        if (row.parentId) {
            children = row.children;
        } else children = treeData.value;
        const index =
            children?.length > 0
                ? children?.map((item) => item.sortIndex)
                : [0];
        sortIndex = Math.max(...index) + 1;
    }

    dialog.selectItem = { ...row, sortIndex };
    dialog.visible = true;
};

const init = () => {
    getTree(save ? openDialog : undefined);
    watch(selectedKeys, (n) => {
        emits('change', n[0]);
    });
};

init();
</script>

<style lang="less" scoped>
.left-tree-container {
    padding-right: 24px;
    border-right: 1px solid #f0f0f0;
    display: flex;
    height: 100%;
    flex-direction: column;

    .add-btn {
        margin: 24px 0;

        :deep(.ant-btn-primary) {
            width: 100%;
        }
    }
    :deep(.ant-tree-treenode) {
        width: 100%;
        .ant-tree-node-content-wrapper {
            flex: 1 1 auto;

            .ant-tree-title {
                &:hover {
                    .func-btns {
                        display: block;
                    }
                }
            }
        }
    }

    .tree {
        overflow-y: auto;
        overflow-x: auto;
        flex: 1 1 auto;
        .department-tree-item-content {
            display: flex;
            align-items: stretch;

            .title {
                flex: 1;
                min-width: 80px;
                margin-right: 80px;
            }
            .func-btns {
                display: none;
                font-size: 14px;
                width: 80px;
                margin-left: -80px;
                :deep(.ant-btn-link) {
                    padding: 0 4px;
                    height: 24px;
                }
            }
        }

        .loading {
            display: flex;
            width: 100%;
            justify-content: center;
            margin-top: 20px;
        }
    }
}
</style>
